package com.example.demo.auth;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

/**
 * 
 * 接口鉴权工具类
 * 
 * @author gwx 2017-12-23
 *
 */
public class AuthenticationKit {
	public static final String utf8="UTF-8";
	
	/**
	 * 返回64 位 token
	 * 
	 * @param key 自定义安全字符
	 * @return
	 * @throws Exception
	 */
	public static String getToken(String key) throws Exception {
		// 随机生成 32位字符
		String salt = HashKit.generateSaltForSha256();
		// 获取当前时间
		long cur = System.currentTimeMillis();
		// 生成64位token
		String access_token = getToken256(key, salt, cur);
		return access_token;
	}
	
	/**
	 * 返回64 位 token
	 * 
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String getToken256(String key, String salt, long cur) throws Exception {
		// 生成64位token
		String access_token = HashKit.sha256(salt + cur + key);
		return access_token;
	}

	/**
	 * 返回到秒
	 * 
	 * @return
	 */
	public static String createTimestamp() {
		long l = System.currentTimeMillis();
		return Long.toString(l / 1000);
	}

	/**
	 * 返回noce 不带 短杠"-"
	 * 
	 * @return
	 */
	public static String createNonceStr() {
		return getUUID();
	}

	public static String getUUID() {
		UUID uuid = UUID.randomUUID();
		String str = uuid.toString();
		str = str.replaceAll("-", "");
		return str;
	}

	/**
	 * 组装路径
	 * 
	 * @param params
	 * @return
	 */
	public static String localSignParam(Map<String, String> params) {
		return localSignUrl(null, params, false);
	}

	
	/**
	 * 组装签名路径
	 * @param url
	 * @param params
	 * @return
	 */
	public static String localSignUrl(String url, Map<String, String> params, boolean urlEncode) {
        StringBuilder strBuilder = new StringBuilder();
        if(StringUtils.isNotBlank(url) && url.lastIndexOf("?")==-1){
        	strBuilder.append(url).append("?");
        }
        boolean seeOne = false;
        for (String key : params.keySet()) {
            if (params.get(key) != null) {
            	String lowerKey = key.toLowerCase();
            	String encodeKey = lowerKey;
            	String encodedValue = params.get(key);
                if (urlEncode){
                	encodeKey = UrlEncoderUtils.encode(lowerKey);
                	encodedValue = UrlEncoderUtils.encode(encodedValue);
                }
                if (!seeOne) {
                	seeOne = true;
                } else {
                	strBuilder.append("&");
                }
                strBuilder.append(encodeKey).append("=").append(encodedValue);
            }
        }
        return strBuilder.toString();
    }

	/**
	 * 加密签名路径生成签名
	 * 
	 * @param signUrl
	 *            /token?appid=12345&timestamp=1512440267&nonce=12345
	 * @param encryptKey
	 * @return
	 * @throws Exception
	 */
	public static String signUrlEncode(String signUrl, String encryptKey) throws Exception {
		byte[] signByte = HMACSHA1.HmacSHA1Encrypt(signUrl, encryptKey);
		String localSign = Base64.encodeBase64String(signByte);
		return localSign;
	}

	/**
	 * 返回鉴权 签名路径
	 * 
	 * @param req
	 * @return
	 */
	public static String getSignUrl(HttpServletRequest req) {
		return getSignUrl(req,"");
	}

	/**
	 * 服务端 获取 客户端请求 组装验证签名
	 * @param req
	 * @param delParams 移除不相关 的签名参数
	 * @return
	 */
	public static String getSignUrl(HttpServletRequest req, String... delParams) {
		// 获取相对的访问路径
		String url = req.getServletPath();
		Map<String, String> paramMap = packageRequestGetParams(req);
		if (paramMap.size() > 0) {
			// 删除
			for (int i = 0, len = delParams.length; i < len; i++) {
				paramMap.remove(delParams[i]);
			}
			return localSignUrl(url, paramMap, false);
		}
		return null;
	}


	/**
	 * 组装签名路径 客户端测试用
	 * @param url api访问地址 "/apid"
	 * @param appid 
	 * @return
	 */
	public static String getSignUrl(String url, String appid, Map<String, String> queryParas) {
		Map<String, String> params = new TreeMap<String, String>();
		params.put("appid", appid);
		params.put("nonce", createNonceStr());
		params.put("timestamp", createTimestamp());
		if(queryParas!=null && queryParas.size()>0){
			params.putAll(queryParas);
		}
		return localSignUrl(url, params, false);
	}
	
	/**
	 * 组装签名路径 客户端测试用
	 * @param url api访问地址 "/apid"
	 * @param appid 
	 * @return
	 */
	public static String getSignUrl(String url, String appid) {
		return getSignUrl(url, appid, "");
	}
	
	/**
	 * 
	 * @param url
	 * @param appid
	 * @param params
	 * @return
	 */
	public static String getSignUrl(String url, String appid, String params) {
		String urlTmp = getSignUrl(url, appid, new HashMap<String,String>());
		return urlTmp + UrlEncoderUtils.encode(params);
	}

	/**
	 * 解析get参数返回treemap
	 * @param req
	 * @return
	 */
	public static Map<String, String> packageRequestGetParams(
			HttpServletRequest req) {
		Map<String, String> paramMap = new TreeMap<String, String>();
		Enumeration pNames = req.getParameterNames();
		while (pNames.hasMoreElements()) {
			String key = (String) pNames.nextElement();
			String value = req.getParameter(key);
			paramMap.put(key, value);
		}
		return paramMap;
	}

}
